import 'dart:ui';

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/services.dart';
import 'package:flutter_svg/flutter_svg.dart' as svg;
import 'package:get/get.dart';
import 'package:hixing_app/assets/r_img.dart';
import 'package:hixing_app/utils/export_utils.dart';
import 'package:hixing_app/views/test_view/canvas_utils.dart';
import 'package:hixing_app/views/test_view/reset_test_matrix4/model/matrix4_data_model.dart';
import 'package:hixing_app/views/test_view/test_matrix4/rect_element_model.dart';
import 'package:hixing_app/views/test_view/test_matrix4/transform_vertex_model.dart';
import 'package:vector_math/vector_math_64.dart' as vector;
import 'dart:math' as math;

class ComputedMatrix4 extends StatefulWidget {
  @override
  _ComputedMatrix4State createState() => _ComputedMatrix4State();
}

class _ComputedMatrix4State extends State<ComputedMatrix4> {
  // 是否锁定比例
  bool isLock = true;

  //
  bool isNeedToFix = false;

  // 触摸开始的点的数据
  Offset startPosition = Offset(0, 0);

  // 点击矩形列表
  List<RectInfoModel> rectList = [];

  // 当前操作事件
  CanvasEventType? eventType;
  CanvasEventType? lasteventType;

  // 计算旋转后 左上角顶点跟0，0原点的偏移量，用来处理旋转后缩放不固定左上角的问题
  Offset fixRotateOffset = Offset(0, 0);

  // 定义矩阵
  Matrix4 matrix4 = Matrix4.identity();

// 定义矩阵数据，每次开始操作前，把上一次的矩阵解析出来，重新赋值到下一次的矩阵操作里面，再从新的矩阵操作里面执行变换数据
  Matrix4DataModel matrix4Data = Matrix4DataModel(
      dx: 100,
      dy: 100,
      scaleX: 1,
      scaleY: 1,
      rotationAngle: 0,
      skewX: 0,
      skewY: 0);
  Matrix4DataModel lastMatrix4Data = Matrix4DataModel(
      dx: 0, dy: 0, scaleX: 1, scaleY: 1, rotationAngle: 0, skewX: 0, skewY: 0);

  Offset centerOffset = Offset.zero;
  Size imgSize = const Size(100, 100);
  Size iconSize = const Size(30, 30);
  svg.PictureInfo? imgSvgPicture;

  Future<void> loadImg() async {
    var pgSvg = await rootBundle.loadString(ImgR.imgBgPguinSVG);
    final svg.PictureInfo pictureInfo1 = await svg.vg.loadPicture(
        svg.SvgStringLoader(
          pgSvg,
        ),
        null);
    setState(() {
      imgSvgPicture = pictureInfo1;
    });
  }

  Widget addListen({required Widget child}) {
    return Listener(
      onPointerUp: (details) {
        Matrix4DataModel data = Matrix4ToData(matrix4);
        // 记录偏移量
        if (eventType == CanvasEventType.rotate) {
          // 计算两个矩阵之间的dx跟dy偏移量，旋转的时候补偿回去
          fixRotateOffset = Offset(
              data.dx - lastMatrix4Data.dx, data.dy - lastMatrix4Data.dy);
        }
        if (eventType == CanvasEventType.scale) {
          // 缩放后。抬起计算中心值
          // 计算四个顶点的当前位置
          List<Offset> _vertext = getVertex(imgSize: imgSize, matrix: matrix4);

          // 获取dx，dy的值
          Matrix4DataModel matrix4Data = Matrix4ToData(matrix4);

          // 绘制图片的矩形操作框
          Path imgTapPath = Path()
            ..moveTo(_vertext[0].dx, _vertext[0].dy); // 移动到第一个顶点
          for (int i = 1; i < _vertext.length; i++) {
            imgTapPath.lineTo(_vertext[i].dx, _vertext[i].dy); // 添加线段
          }
          imgTapPath.close(); // 封闭路径
          // 绘制一个不旋转的矩形
          Rect centerToRect = imgTapPath.getBounds();
          centerOffset = centerToRect.center;
          print(centerToRect);
        }

        lastMatrix4Data = data;

        centerOffset = Offset(imgSize.width * matrix4Data.scaleX / 2,
            imgSize.height * matrix4Data.scaleY / 2);
        lasteventType = eventType;
        eventType = null;
        setState(() {});
      },
      onPointerDown: (details) {
        double topHeight = ScreenUI.topSafeHeight + 60;
        // 获取移动的位置,把导航高度去掉
        final position = details.position - Offset(0, topHeight);
        startPosition = position;

        // 循环矩形点击域，添加点击事件
        for (var element in rectList) {
          if (element.path != null) {
            if (element.path!.contains(position)) {
              eventType = element.type;
              print("element event ：${element.type}");
              if (eventType == CanvasEventType.image) {
              } else if (eventType == CanvasEventType.scale) {
              } else if (eventType == CanvasEventType.lock) {
              } else if (eventType == CanvasEventType.rotate) {
                // if(eventType!=)
                // if (lasteventType == CanvasEventType.rotate) {
                //   lastMatrix4Data.dx -= fixRotateOffset.dx;
                //   lastMatrix4Data.dy -= fixRotateOffset.dy;
                //   isNeedToFix = true;
                // }
                // else {
                //   lastMatrix4Data.dx += fixRotateOffset.dx;
                //   lastMatrix4Data.dy += fixRotateOffset.dy;
                // }
              }
              break;
            }
          }
        }
      },
      onPointerMove: (details) {
        double topHeight = ScreenUI.topSafeHeight + 60;
        // 获取移动的位置,把导航高度去掉
        final position = details.position - Offset(0, topHeight);
        // 移动开始前的点位减去移动时的点位，计算出偏移量
        final boxPosition = position - startPosition;

        if (eventType == CanvasEventType.image) {
          print("move事件：${position - startPosition}");
          matrix4Data = Matrix4DataModel(
            dx: lastMatrix4Data.dx + boxPosition.dx,
            dy: lastMatrix4Data.dy + boxPosition.dy,
            scaleX: lastMatrix4Data.scaleX,
            scaleY: lastMatrix4Data.scaleY,
            rotationAngle: lastMatrix4Data.rotationAngle,
            skewX: 0,
            skewY: 0,
          );
          matrix4 = DataToMatrix4(matrix4Data, imgSize: imgSize);
          setState(() {});
        } else if (eventType == CanvasEventType.scale) {
          // 这里把上一次的缩放值放回去了
          // double oldWidth = imgSize.width * lastMatrix4Data.scaleX;
          // double oldHeight = imgSize.height * lastMatrix4Data.scaleY;
          double currentScaleX =
              (imgSize.width + boxPosition.dx) / imgSize.width;
          double currentScaleY =
              (imgSize.height + boxPosition.dy) / imgSize.height;
          if (isLock) {
            // 等比
            double equalScale = (currentScaleX + currentScaleY) / 2;
            currentScaleX = equalScale;
            currentScaleY = equalScale;
          }
          matrix4Data = Matrix4DataModel(
              dx: lastMatrix4Data.dx,
              dy: lastMatrix4Data.dy,
              // 这里需要把上一次缩放的自身尺寸给减掉，剩下的就是缩放后尺寸-原始尺寸，把剩余的偏移量加回来;
              scaleX: (lastMatrix4Data.scaleX - 1) + currentScaleX,
              scaleY: (lastMatrix4Data.scaleY - 1) + currentScaleY,
              rotationAngle: lastMatrix4Data.rotationAngle,
              skewX: 0,
              skewY: 0);
          matrix4 = DataToMatrix4(
            matrix4Data,
            imgSize: imgSize,
          );
          setState(() {});
        } else if (eventType == CanvasEventType.rotate) {
          // 求出初始坐标跟移动坐标后的方位角
          final angle = math.atan2(boxPosition.dy, boxPosition.dx);
          // print(
          //     "上一次的缩放尺寸：${lastMatrix4Data.scaleX},${lastMatrix4Data.scaleY}");
          // 计算四个顶点的当前位置

          matrix4Data = Matrix4DataModel(
            dx: lastMatrix4Data.dx,
            dy: lastMatrix4Data.dy,
            // 这里需要把上一次缩放的自身尺寸给减掉，剩下的就是缩放后尺寸-原始尺寸，把剩余的偏移量加回来;
            scaleX: lastMatrix4Data.scaleX,
            scaleY: lastMatrix4Data.scaleY,
            rotationAngle: lastMatrix4Data.rotationAngle + (angle * 1),
            skewX: 0,
            skewY: 0,
          );

          matrix4 = DataToMatrix4(matrix4Data,
              eventType: eventType!,
              imgSize: imgSize,
              centerOffset: centerOffset);

          setState(() {});
        }
      },
      child: child,
    );
  }

  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    centerOffset = Offset(imgSize.width / 2, imgSize.height / 2);
    matrix4 = DataToMatrix4(matrix4Data, imgSize: imgSize);
    lastMatrix4Data = Matrix4ToData(matrix4);
    loadImg();
    // SystemChrome.setPreferredOrientations(// 使设备横屏显示
    //     [DeviceOrientation.landscapeLeft, DeviceOrientation.landscapeRight]);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: PreferredSize(
        preferredSize: Size.fromHeight(60),
        child: AppBar(
          title: Text("创作"),
          actions: [
            GestureDetector(
              onTap: () {
                isLock = !isLock;
                setState(() {});
              },
              child: Container(
                padding: EdgeInsets.all(10),
                decoration: BoxDecoration(
                    color: Colors.black26,
                    borderRadius: BorderRadius.circular(40)),
                child: Text(isLock ? '解锁' : '锁定'),
              ),
            ),
          ],
        ),
      ),
      body: Column(
        children: [
          Expanded(
            child: addListen(
              child: SingleChildScrollView(
                scrollDirection: isLock ? Axis.vertical : Axis.horizontal,
                physics: eventType == null
                    ? ClampingScrollPhysics()
                    : NeverScrollableScrollPhysics(),
                child: CustomPaint(
                  size: const Size(2000.0, 2000.0),
                  painter: MyCustomPainter(
                      matrix4: matrix4,
                      eventType: eventType,
                      rectList: rectList,
                      imgPicture: imgSvgPicture,
                      imgSize: imgSize,
                      iconSize: iconSize),
                ),
              ),
            ),
          ),
        ],
      ),
    );
  }
}

class MyCoorPainter extends CustomPainter {
  Paint _paint = Paint();

  //边距
  double padding = 40;

  // 整除数
  double floorNum = 320;

  // step
  double step = 10;
  Size _size = Size(4000.0, 4000.0);

  @override
  void paint(Canvas canvas, Size size) {
    // TODO: implement paint
    CanvasUtils.drawGrid(canvas, _paint, size);
    CanvasUtils.drawCoor(canvas, _paint, _size);
    drawRuler(canvas, _paint, axis: Axis.vertical, size: _size.height);
    drawRuler(canvas, _paint, axis: Axis.horizontal, size: _size.width);
  }

  void drawRuler(Canvas canvas, Paint paint,
      {required Axis axis, required double size}) {
    canvas.save();
    Offset initOffset =
        axis == Axis.vertical ? Offset(0, padding) : Offset(padding, 0);
    canvas.translate(initOffset.dx, initOffset.dy);

    _paint..color = Colors.red;
    int _xNum = size ~/ floorNum;
    for (int i = 0; i < _xNum; i++) {
      if (axis == Axis.vertical) {
        canvas.drawLine(Offset(0, 0), Offset(padding, 0), _paint);
      } else {
        canvas.drawLine(Offset(0, 0), Offset(0, padding), _paint);
      }

      CanvasTextPainter.drawText(
          canvas: canvas,
          text: "${(i * floorNum).toInt()}",
          offset: Offset(8, 6),
          fontSize: 12,
          color: Colors.black);
      drawSmallLine(canvas, axis);
      if (axis == Axis.vertical) {
        canvas.translate(0, step * 10);
      } else {
        canvas.translate(step * 10, 0);
      }
      if (i == _xNum - 1) {
        if (axis == Axis.vertical) {
          canvas.drawLine(Offset(0, 0), Offset(padding, 0), _paint);
        } else {
          canvas.drawLine(Offset(0, 0), Offset(0, padding), _paint);
        }
      }
    }

    canvas.restore();
  }

  drawSmallLine(Canvas canvas, Axis axis) {
    canvas.save();
    // canvas.drawLine(Offset(padding - 4, 0), Offset(padding, 0), _paint);
    List.generate(10, (index) {
      Offset dOffset = axis == Axis.vertical
          ? Offset(padding - 4, 0)
          : Offset(0, padding - 4);
      if (index == 5) {
        dOffset = axis == Axis.vertical
            ? Offset(padding - 14, 0)
            : Offset(0, padding - 14);
      }
      if (axis == Axis.vertical) {
        canvas.drawLine(dOffset, Offset(padding, 0), _paint);
        canvas.translate(0, step);
      } else {
        canvas.drawLine(Offset(0, padding), dOffset, _paint);
        canvas.translate(step, 0);
      }
    });
    canvas.restore();
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) {
    // TODO: implement shouldRepaint
    return true;
  }
}

// 计算旋转后的中心点位置  旋转前的中心，旋转的中心点，
Offset rotatePoint(Offset point, double angle, Offset rotationCenter) {
  double cosTheta = math.cos(angle);
  double sinTheta = math.sin(angle);

  // 平移到原点
  double translatedX = point.dx - rotationCenter.dx;
  double translatedY = point.dy - rotationCenter.dy;

  // 应用旋转
  double rotatedX = translatedX * cosTheta - translatedY * sinTheta;
  double rotatedY = translatedX * sinTheta + translatedY * cosTheta;

  // 平移回原来的中心
  return Offset(rotatedX + rotationCenter.dx, rotatedY + rotationCenter.dy);
}

Matrix4 DataToMatrix4(
  Matrix4DataModel data, {
  required Size imgSize,
  Offset centerOffset = const Offset(0, 0),
  CanvasEventType eventType = CanvasEventType.scale,
}) {
  Matrix4 scaleMatrix4 = Matrix4.identity()..scale(data.scaleX, data.scaleY);

  Matrix4 rotateMatrix4 = Matrix4.identity();
  rotateMatrix4
    ..translate(centerOffset.dx, centerOffset.dy) // 移动到中心
    ..rotateZ(data.rotationAngle)
    ..translate(-centerOffset.dx, -centerOffset.dy); // 移回原位

  Matrix4 translateMatrix4 = Matrix4.identity()..translate(data.dx, data.dy);
  return translateMatrix4 * rotateMatrix4 * scaleMatrix4;
}

Matrix4DataModel Matrix4ToData(Matrix4 matrix4) {
  // 创建用于接收分解结果的变量
  vector.Vector3 translation = vector.Vector3.zero();
  vector.Quaternion rotation = vector.Quaternion.identity();
  vector.Vector3 scale = vector.Vector3.zero();
  // 分解矩阵
  matrix4.decompose(translation, rotation, scale);

  vector.Vector3 position = matrix4.getTranslation();
  double scaleX = scale.x;
  double scaleY = scale.y;
  double angle = math.atan2(matrix4.storage[1], matrix4.storage[0]);
  double skewX = 0;
  double skewY = 0;
  // 获取旋转角度
  // print("旋转角度（度）:${angle} ${angle * 180 / math.pi}");
  return Matrix4DataModel(
      dx: position.x,
      dy: position.y,
      scaleX: scaleX,
      scaleY: scaleY,
      rotationAngle: angle,
      skewY: skewY,
      skewX: skewX);
}

class MyCustomPainter extends CustomPainter {
  MyCustomPainter(
      {required this.matrix4,
      required this.imgPicture,
      required this.imgSize,
      required this.rectList,
      required this.eventType,
      required this.iconSize});

  final Matrix4 matrix4;
  final svg.PictureInfo? imgPicture;
  final Size imgSize;
  final Size iconSize;
  List<RectInfoModel> rectList;
  final CanvasEventType? eventType;

  @override
  void paint(Canvas canvas, Size size) {
    // TODO: implement paint
    rectList.clear();
    Rect imgRect = Rect.fromLTWH(0, 0, imgSize.width, imgSize.height);
    Paint _paint = Paint();
    MyCoorPainter().paint(canvas, size);

    canvas.save();

    canvas.transform(matrix4.storage);

    canvas.drawRect(imgRect, _paint..color = Colors.red);
    if (imgPicture != null) {
      // 绘制企鹅 svg  尺寸是imgSize
      CanvasUtils.drawResizeSvg(
          canvas, imgPicture!.picture, imgSize, imgPicture!.size,
          color: null);
    }
    canvas.restore();

    canvas.save();
    // 计算四个顶点的当前位置
    List<Offset> _vertext = getVertex(imgSize: imgSize, matrix: matrix4);

    // 把给点位坐标添加命名
    TransformVertexModel transformVertex = TransformVertexModel(
      topLeft: _vertext[0],
      topRight: _vertext[1],
      bottomRight: _vertext[2],
      bottomLeft: _vertext[3],
    );

    // 获取dx，dy的值
    Matrix4DataModel matrix4Data = Matrix4ToData(matrix4);

    // 绘制图片的矩形操作框
    Path imgTapPath = Path()
      ..moveTo(_vertext[0].dx, _vertext[0].dy); // 移动到第一个顶点
    for (int i = 1; i < _vertext.length; i++) {
      imgTapPath.lineTo(_vertext[i].dx, _vertext[i].dy); // 添加线段
    }
    imgTapPath.close(); // 封闭路径

    // 绘制矩形
    _paint
      ..color = Colors.orangeAccent
      ..style = PaintingStyle.stroke
      ..strokeWidth = 2.0;

    //把dx dy 偏移量加回去
    imgTapPath = imgTapPath.shift(Offset(matrix4Data.dx, matrix4Data.dy));

    // canvas.translate(50, 200);
    canvas.drawPath(imgTapPath, _paint);
    rectList.add(RectInfoModel(
        rect: Rect.zero, path: imgTapPath, type: CanvasEventType.image));

    // 绘制一个不旋转的矩形
    Rect centerToRect = imgTapPath.getBounds();
    // centerToRect = centerToRect.shift(Offset(matrix4Data.dx, matrix4Data.dy));

    canvas.drawRect(centerToRect, _paint..color = Colors.purple);

    // 绘制右下角缩放的操作按钮
    Path scaleTapPath = Path()
      ..moveTo(transformVertex.bottomRight.dx,
          transformVertex.bottomRight.dy); // 移动到第一个顶点
    scaleTapPath
      ..relativeLineTo(30, 0)
      ..relativeLineTo(0, 30)
      ..relativeLineTo(-30, 0);

    scaleTapPath.close(); // 封闭路径
    //把dx dy 偏移量加回去
    scaleTapPath = scaleTapPath.shift(Offset(matrix4Data.dx, matrix4Data.dy));
    _paint
      ..color = Colors.red
      ..style = PaintingStyle.stroke
      ..strokeWidth = 2.0;
    // canvas.translate(50, 200);
    canvas.drawPath(scaleTapPath, _paint);
    rectList.add(RectInfoModel(
        rect: Rect.zero, path: scaleTapPath, type: CanvasEventType.scale));
    drawRoateIcon(
        canvas: canvas,
        paint: _paint,
        transformVertex: transformVertex,
        matrix4Data: matrix4Data);
    canvas.restore();
  }

  drawRoateIcon({
    required Canvas canvas,
    required Paint paint,
    required TransformVertexModel transformVertex,
    required Matrix4DataModel matrix4Data,
  }) {
    canvas.save();
    // 绘制右上角缩放的操作按钮
    Path rotateTapPath = Path()
      ..moveTo(
          transformVertex.topRight.dx, transformVertex.topRight.dy); // 移动到第一个顶点
    rotateTapPath
      ..relativeLineTo(30, 0)
      ..relativeLineTo(0, -30)
      ..relativeLineTo(-30, 0);
    rotateTapPath.close(); // 封闭路径
    //把dx dy 偏移量加回去
    rotateTapPath = rotateTapPath.shift(Offset(matrix4Data.dx, matrix4Data.dy));
    paint
      ..color = Colors.red
      ..style = PaintingStyle.stroke
      ..strokeWidth = 2.0;
    // canvas.translate(50, 200);
    canvas.drawPath(rotateTapPath, paint);
    rectList.add(RectInfoModel(
        rect: Rect.zero, path: rotateTapPath, type: CanvasEventType.rotate));
    canvas.restore();
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) {
    // TODO: implement shouldRepaint
    return true;
  }
}

// 获取旋转后的矩形的中心点
Offset getRectangleCenter(List<Offset> points) {
  double sumX = 0.0;
  double sumY = 0.0;

  for (Offset point in points) {
    sumX += point.dx;
    sumY += point.dy;
  }

  return Offset(sumX / points.length, sumY / points.length);
}

// 获取变换后的四个顶点
List<Offset> getVertex(
    {required Size imgSize,
    required Matrix4 matrix,
    bool useCenterPoint = false}) {
  // 使用0，0原点旋转
  Offset originTopLeft = const Offset(0, 0);
  Offset originTopRight = Offset(imgSize.width, 0);
  Offset originBottomRight = Offset(
    imgSize.width,
    imgSize.height,
  );
  Offset originBottomLeft = Offset(0, imgSize.height);

  if (useCenterPoint) {
    // useCenterPoint 使用中心原点旋转，可以计算旋转后跟以原点绘制的矩形的旋转偏移量，从而计算旋转后左上角缩放固定不准的问题
    originTopLeft = Offset(-imgSize.width / 2, -imgSize.height / 2);
    originTopRight = Offset(imgSize.width / 2, -imgSize.height / 2);
    originBottomRight = Offset(
      imgSize.width / 2,
      imgSize.height / 2,
    );
    originBottomLeft = Offset(-imgSize.width / 2, imgSize.height / 2);
  }

  vector.Vector4 topLef = vector.Vector4(
      originTopLeft.dx, originTopLeft.dy, 0, 0); // 使用Vector3表示一个点;
  vector.Vector4 topRight = vector.Vector4(
      originTopRight.dx, originTopRight.dy, 0, 0); // 使用Vector3表示一个点;

  vector.Vector4 bottomRight = vector.Vector4(
      originBottomRight.dx, originBottomRight.dy, 0, 0); // 使用Vector3表示一个点;

  vector.Vector4 bottomLeft = vector.Vector4(
      originBottomLeft.dx, originBottomLeft.dy, 0, 0); // 使用Vector3表示一个点;

  vector.Vector4 topLeftPosition = matrix.transformed(topLef);
  vector.Vector4 topRightPosition = matrix.transformed(topRight);
  vector.Vector4 bottomRightPosition = matrix.transformed(bottomRight);
  vector.Vector4 bottomLeftPosition = matrix.transformed(bottomLeft);
  return [
    Offset(topLeftPosition.x, topLeftPosition.y),
    Offset(topRightPosition.x, topRightPosition.y),
    Offset(bottomRightPosition.x, bottomRightPosition.y),
    Offset(bottomLeftPosition.x, bottomLeftPosition.y),
  ];
}

class CanvasTextPainter {
  static void drawText({
    required Canvas canvas,
    required String text,
    required Offset offset,
    double? fontSize,
    Color? color,
    FontWeight? fontWeight,
    TextAlign? textAlign,
  }) {
    final textSpan = TextSpan(
      text: text,
      style: TextStyle(
        color: color ?? Colors.black,
        fontSize: fontSize ?? 14,
        fontWeight: fontWeight ?? FontWeight.normal,
      ),
    );

    final textPainter = TextPainter(
      text: textSpan,
      textAlign: textAlign ?? TextAlign.left,
      textDirection: TextDirection.ltr,
    );

    textPainter.layout(minWidth: 0, maxWidth: double.infinity);
    textPainter.paint(canvas, offset);
  }
}
